home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Hardware / BetaScan / BetaScanDev / TestSrc / makeILBM.c next >
Encoding:
C/C++ Source or Header  |  1999-01-23  |  12.9 KB  |  501 lines

  1. /************************************************************************/
  2. /*                                                                      */
  3. /* Write image as ilbm                                                  */
  4. /*                                                                      */
  5. /*                                                                      */
  6. /*                                                                      */
  7. /*                                                                      */
  8. /************************************************************************/
  9.  
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13.  
  14. #include <exec/types.h>
  15. #include <datatypes/pictureclass.h>
  16.  
  17. #include <scanner.h>
  18. #include <MakeILBM.h>
  19. #include <packer.h>
  20.  
  21. #define ID_XBMI MAKE_ID('X','B','M','I')
  22. #define ILBM_BUFLEN 1500000
  23.  
  24. struct ImageBuf
  25. {
  26.   UBYTE* buf;
  27.   ULONG  actualLen;
  28.   FILE*  fh;
  29. };
  30.  
  31. struct ILBMFile
  32. {
  33.   char* fileName;
  34.   int   formLenOffset;
  35.   int   bodyLenOffset;
  36.   UBYTE flags;
  37.   
  38.   UBYTE depth;
  39.   UWORD width;
  40.   UWORD height;
  41.   UWORD xdpi;
  42.   UWORD ydpi;
  43.  
  44.   LineFormat format;
  45.  
  46.   ULONG scanLineWidth;
  47.   ULONG bufLen;
  48.   struct ImageBuf buf[3];
  49. };
  50.  
  51. #define ILBMFLAGS_COMPRESS  (0x01 << 0)
  52. #define ILBMFLAGS_TEMPFILE  (0x01 << 1)
  53.  
  54. struct xbmi
  55. {
  56.   WORD xbmi_type;   /* ILBM_PAL, ILBM_RGB, ... (se below) */
  57.   WORD xbmi_xdpi;
  58.   WORD xbmi_ydpi;
  59. };
  60.  
  61.  
  62. #define ILBM_PAL        0       /* BODY data = indexes into the palette (CMAP)
  63.                                  * numcolors = 1<<depth;
  64.                                  */
  65.  
  66. #define ILBM_GREY       1       /* BODY =  grayscale values
  67.                                  * Bits per sample = number of bitplanes.
  68.                                  * Samples per pixel = 1.
  69.                                  * black = 0, white = (1<<depth)-1;
  70.                                  */
  71.  
  72. #define ILBM_RGB        2       /* BODY data = red, green, and blue values.
  73.                                  * Bits per sample = depth/3.
  74.                                  * Samples per pixel = 3.
  75.                                  */
  76.  
  77. #define ILBM_RGBA       3       /* BODY data = red, green, blue, and alpha
  78.                                  * channel values.
  79.                                  * Bits per sample = depth/4.
  80.                                  * Samples per pixel = 4.
  81.                                  */
  82.  
  83. #define ILBM_CMYK       4       /* BODY data = cyan, magenta, yellow, and black
  84.                                  * values.
  85.                                  * Bits per sample = depth/4.
  86.                                  * Samples per pixel = 4.
  87.                                  */
  88.  
  89. #define ILBM_CMYKA      5       /* BODY data = cyan, magenta, yellow, black,
  90.                                  * and alpha channel values.
  91.                                  * Bits per sample = depth/5.
  92.                                  * Samples per pixel = 5.
  93.                                  */
  94.  
  95. #define ILBM_BW         6       /* BODY data = black and white bits.
  96.                                  * Bits per sample = 1.
  97.                                  * Samples per pixel = 1.
  98.                                  * white = 0, black = 1.
  99.                                  */
  100.  
  101. static char* tempfile[3] = {"ram:temp.red","ram:temp.green","ram:temp.blue"};
  102.  
  103. static void makePlane(UBYTE* source,UBYTE* dest,int bit,int pixelPerLine,int bytesPerPixel)
  104. {
  105.   int   bitNum,byteNum,offset;
  106.   UBYTE b,sourceMask;
  107.  
  108.   offset = bit/8;
  109.   bit %= 8;
  110.   
  111.   sourceMask = 0x01 << bit;
  112.   
  113.   source += offset;
  114.   for( byteNum = 0 ; byteNum < pixelPerLine ; byteNum++ )
  115.   {
  116.     UBYTE destMask;
  117.     
  118.     destMask = 0x80;
  119.     b = 0;
  120.     for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
  121.     {
  122.       if( (*source) & sourceMask )
  123.         b |= destMask;
  124.  
  125.       destMask >>= 1;
  126.       source += bytesPerPixel;
  127.     }
  128.     *(dest++) = b;
  129.   }
  130.  
  131. static void makeILBM(struct ILBMFile* ilbmfh)
  132. {
  133.   struct BitMapHeader BMHD;
  134.   struct xbmi         XBMI;
  135.   FILE*  fh;
  136.   int    c;
  137.   
  138.   if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  139.   {
  140.     for( c = 0 ; c < 3 ; c++ )
  141.     {
  142.       if( ilbmfh->buf[c].fh && (ilbmfh->buf[c].fh = fopen(tempfile[c],"r")) )
  143.         setvbuf(ilbmfh->buf[c].fh,ilbmfh->buf[c].buf,_IOFBF,ilbmfh->bufLen);
  144.     }
  145.   }
  146.   
  147.   BMHD.bmh_Width = ilbmfh->width;
  148.   BMHD.bmh_Height = ilbmfh->height;
  149.   BMHD.bmh_Left = 0;
  150.   BMHD.bmh_Top = 0;
  151.   BMHD.bmh_Depth = ilbmfh->depth;
  152.   BMHD.bmh_Masking = 0;
  153.   BMHD.bmh_Pad = 0;
  154.   BMHD.bmh_Transparent = 0;
  155.   BMHD.bmh_XAspect = 1;
  156.   BMHD.bmh_YAspect = 1;
  157.   BMHD.bmh_PageWidth = ilbmfh->width;
  158.   BMHD.bmh_PageHeight = ilbmfh->height;
  159.   
  160.   switch( ilbmfh->depth )
  161.   {
  162.     case 1:
  163.       XBMI.xbmi_type = ILBM_BW;
  164.       break;
  165.     case 8:
  166.       XBMI.xbmi_type = ILBM_GREY;
  167.       break;
  168.     case 24:
  169.       XBMI.xbmi_type = ILBM_RGB;
  170.       break;
  171.   }        
  172.   XBMI.xbmi_xdpi = ilbmfh->xdpi;
  173.   XBMI.xbmi_ydpi = ilbmfh->ydpi;
  174.  
  175.   if( fh = fopen(ilbmfh->fileName,"w") )
  176.   {
  177.     int scanLine,color,bitNum;
  178.     ULONG lineLen,bodyLen,formLen;
  179.     ULONG temp,psize;
  180.     UBYTE *line;
  181.     UBYTE *pline = NULL;
  182.     UBYTE *scanbuf = NULL;
  183.  
  184.     lineLen = ((ilbmfh->width+7)/8+1) & 0xFFFFFFFE; // Number of bits in each plane row
  185.                                                     // Rounded up to an even number of words
  186.     line = malloc(ilbmfh->format==FORMAT_RGB?3*lineLen:lineLen);
  187.     if( (ilbmfh->flags & ILBMFLAGS_COMPRESS) && (pline = malloc(ilbmfh->format==FORMAT_RGB?6*lineLen:lineLen*2)) )
  188.       BMHD.bmh_Compression = 1;
  189.     else
  190.       BMHD.bmh_Compression = 0;
  191.       
  192.     temp = ID_FORM;
  193.     fwrite(&temp,4,1,fh);
  194.     ilbmfh->formLenOffset = ftell(fh);
  195.     temp = 0;
  196.     fwrite(&temp,4,1,fh);
  197.  
  198.     temp = ID_ILBM;
  199.     fwrite(&temp,4,1,fh);
  200.  
  201.     temp = ID_BMHD;
  202.     fwrite(&temp,4,1,fh);
  203.     temp = sizeof(struct BitMapHeader);
  204.     fwrite(&temp,4,1,fh);
  205.     fwrite(&BMHD,sizeof(struct BitMapHeader),1,fh);
  206.     
  207.     temp = ID_XBMI;
  208.     fwrite(&temp,4,1,fh);
  209.     temp = sizeof(struct xbmi);
  210.     
  211.     fwrite(&temp,4,1,fh);
  212.     fwrite(&XBMI,sizeof(struct xbmi),1,fh);
  213.  
  214.     if( ilbmfh->depth == 1 )
  215.     {
  216.       UBYTE b;
  217.       
  218.       temp = ID_CMAP;
  219.       fwrite(&temp,4,1,fh);
  220.       temp = 3*2;;
  221.       fwrite(&temp,4,1,fh);
  222.  
  223.       b = 0xFF;
  224.       fwrite(&b,1,1,fh);
  225.       fwrite(&b,1,1,fh);
  226.       fwrite(&b,1,1,fh);
  227.  
  228.       b = 0;
  229.       fwrite(&b,1,1,fh);
  230.       fwrite(&b,1,1,fh);
  231.       fwrite(&b,1,1,fh);
  232.     }
  233.     else if( ilbmfh->depth == 8 )
  234.     {
  235.       UBYTE b;
  236.       int   i;
  237.       
  238.       temp = ID_CMAP;
  239.       fwrite(&temp,4,1,fh);
  240.       temp = 3*256;;
  241.       fwrite(&temp,4,1,fh);
  242.       for( i = 0 ;  i < 256 ; i++ )
  243.       {
  244.         b = (UBYTE)i;
  245.         fwrite(&b,1,1,fh);
  246.         fwrite(&b,1,1,fh);
  247.         fwrite(&b,1,1,fh);
  248.       }
  249.     }
  250.     
  251.     temp = ID_BODY;
  252.     fwrite(&temp,4,1,fh);
  253.     ilbmfh->bodyLenOffset = ftell(fh);
  254.     temp = 0;
  255.     fwrite(&temp,4,1,fh);
  256.  
  257.     if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  258.       scanbuf = malloc(ilbmfh->scanLineWidth);
  259.     
  260.     switch( ilbmfh->format )
  261.     {
  262.       case FORMAT_BW:
  263.         for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
  264.         {
  265.           if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  266.             fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
  267.           else
  268.             scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
  269.  
  270.           if( pline == NULL )
  271.             fwrite(scanbuf,lineLen,1,fh);
  272.           else
  273.           {
  274.             psize = PackRow(scanbuf,pline,lineLen);
  275.             fwrite(pline,psize,1,fh);
  276.           }
  277.         }
  278.         break;
  279.       case FORMAT_GRAY:
  280.       case FORMAT_RED:
  281.       case FORMAT_GREEN:
  282.       case FORMAT_BLUE:
  283.         for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
  284.         {
  285.           if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  286.             fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
  287.           else
  288.             scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
  289.           for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
  290.           {
  291.             makePlane(scanbuf,line,bitNum,lineLen,1);
  292.             if( pline == NULL )
  293.               fwrite(line,lineLen,1,fh);
  294.             else
  295.             {
  296.               psize = PackRow(line,pline,lineLen);
  297.               fwrite(pline,psize,1,fh);
  298.             }
  299.           }
  300.         }
  301.         break;
  302.       case FORMAT_RGB:
  303.         for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
  304.         {
  305.           if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  306.             fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
  307.           else
  308.             scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
  309.           for( bitNum = 0 ; bitNum < 24 ; bitNum++ )
  310.           {
  311.             makePlane(scanbuf,line,bitNum,lineLen,3);
  312.             if( pline == NULL )
  313.               fwrite(line,lineLen,1,fh);
  314.             else
  315.             {
  316.               psize = PackRow(line,pline,lineLen);
  317.               fwrite(pline,psize,1,fh);
  318.             }
  319.           }
  320.         }
  321.         break;
  322.       case FORMAT_RGB_RANDOM:
  323.         for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
  324.         {
  325.           for( color = 0 ; color < 3 ; color++ )
  326.           {
  327.             if( ilbmfh->buf[color].buf )
  328.             {
  329.               if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  330.                 fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[color].fh);
  331.               else
  332.                 scanbuf = ilbmfh->buf[color].buf + scanLine*ilbmfh->scanLineWidth;
  333.               for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
  334.               {
  335.                 makePlane(scanbuf,line,bitNum,lineLen,1);
  336.                 if( pline == NULL )
  337.                   fwrite(line,lineLen,1,fh);
  338.                 else
  339.                 {
  340.                   psize = PackRow(line,pline,lineLen);
  341.                   fwrite(pline,psize,1,fh);
  342.                 }
  343.               }
  344.             }
  345.           }
  346.         }
  347.         break;
  348.     }        
  349.     free(line);
  350.     if( pline )
  351.       free(pline);
  352.     if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  353.       free(scanbuf);
  354.  
  355.     for( color = 0 ; color < 3 ; color++ )
  356.     {
  357.       if( ilbmfh->buf[color].fh )
  358.         fclose(ilbmfh->buf[color].fh);
  359.       if( ilbmfh->buf[color].buf )
  360.         free(ilbmfh->buf[color].buf);
  361.     }
  362.  
  363.     // Write FORM and BODY length
  364.     formLen = ftell(fh) - ilbmfh->formLenOffset - 4;
  365.     bodyLen = ftell(fh) - ilbmfh->bodyLenOffset - 4;
  366.  
  367.     fseek(fh,ilbmfh->formLenOffset,SEEK_SET);
  368.     fwrite(&formLen,4,1,fh);
  369.  
  370.     fseek(fh,ilbmfh->bodyLenOffset,SEEK_SET);
  371.     fwrite(&bodyLen,4,1,fh);
  372.     
  373.     fclose(fh);
  374.   }
  375. }
  376.  
  377.  
  378. struct ILBMFile *openILBM(char* name,short compr,struct ScanInformation* info)
  379. {
  380.   struct ILBMFile* fh;
  381.   
  382.   if( fh = calloc(1,sizeof(struct ILBMFile)) )
  383.   {
  384.     fh->fileName = name;
  385.     if( compr )
  386.       fh->flags = ILBMFLAGS_COMPRESS;
  387.     else
  388.       fh->flags = 0;
  389.     fh->depth = info->sv_imageDepth;
  390.     fh->width = info->sv_imageWidth;
  391.     fh->height = info->sv_imageHeight;
  392.     fh->xdpi = (UWORD)(info->sv_xResolution+0.5);
  393.     fh->ydpi = (UWORD)(info->sv_yResolution+0.5);
  394.     fh->format = info->sv_lineFormat;
  395.     fh->scanLineWidth = info->sv_bytesPerLine;
  396.     fh->bufLen = fh->scanLineWidth*fh->height;
  397.     
  398.     switch( fh->format )
  399.     {
  400.       case FORMAT_BW:
  401.       case FORMAT_GRAY:
  402.       case FORMAT_RED:
  403.       case FORMAT_GREEN:
  404.       case FORMAT_BLUE:
  405.       case FORMAT_RGB:
  406.         if( fh->bufLen > ILBM_BUFLEN )
  407.           fh->bufLen = ILBM_BUFLEN;
  408.         fh->buf[0].buf = malloc(fh->bufLen);
  409.         break;
  410.       case FORMAT_RGB_RANDOM:
  411.         {
  412.           int c;
  413.           
  414.           if( 3*fh->bufLen > ILBM_BUFLEN )
  415.             fh->bufLen = ILBM_BUFLEN/3;
  416.             
  417.           for( c = 0 ; c < 3 ; c++ )
  418.             fh->buf[c].buf = malloc(fh->bufLen);
  419.         }
  420.         break;
  421.       default:
  422.         free(fh);
  423.         return NULL;
  424.     }
  425.   }
  426.         
  427.   return fh;
  428. }
  429.  
  430. void closeILBM(struct ILBMFile* ilbmfh,short error)
  431. {
  432.   int    c;
  433.   
  434.   if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  435.   {
  436.     for( c = 0 ; c < 3 ; c++ )
  437.     {
  438.       if( ilbmfh->buf[c].fh )
  439.       {
  440.         fwrite(ilbmfh->buf[c].buf,ilbmfh->buf[c].actualLen,1,ilbmfh->buf[c].fh);
  441.         fclose(ilbmfh->buf[c].fh);
  442.         // ilbmfh->buf[c].fh = NULL;
  443.       }
  444.     }
  445.   }
  446.  
  447.   if( !error )
  448.     makeILBM(ilbmfh);
  449.  
  450.   if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  451.   {
  452.     for( c = 0 ; c < 3 ; c++ )
  453.       remove(tempfile[c]);
  454.   }
  455.  
  456.   free(ilbmfh);
  457. }
  458.  
  459. void writeILBM(struct ILBMFile* fh,struct ScanLine* line)
  460. {
  461.   int cPlane;
  462.   
  463.   if( fh->format == FORMAT_RGB_RANDOM )
  464.   {
  465.     switch( line->sl_color )
  466.     {
  467.       case FORMAT_RED:
  468.         cPlane = 0;
  469.         break;
  470.       case FORMAT_GREEN:
  471.         cPlane = 1;
  472.         break;
  473.       case FORMAT_BLUE:
  474.         cPlane = 2;
  475.         break;
  476.       default:
  477.         return;
  478.     }
  479.   }
  480.   else
  481.     cPlane = 0;
  482.       
  483.   if( fh->buf[cPlane].actualLen + fh->scanLineWidth > fh->bufLen )
  484.   {
  485.     if( fh->buf[cPlane].fh == NULL )
  486.     {
  487.       if( fh->buf[cPlane].fh = fopen(tempfile[cPlane],"w") )
  488.         fh->flags |= ILBMFLAGS_TEMPFILE;
  489.       else
  490.         return;
  491.     }
  492.           
  493.     fwrite(fh->buf[cPlane].buf,fh->buf[cPlane].actualLen,1,fh->buf[cPlane].fh);
  494.     fh->buf[cPlane].actualLen = 0;
  495.   }
  496.  
  497.   memcpy(fh->buf[cPlane].buf+fh->buf[cPlane].actualLen,line->sl_data,fh->scanLineWidth);
  498.   fh->buf[cPlane].actualLen += fh->scanLineWidth;
  499. }
  500.